<!doctype html>
<html lang="zh-CN">
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    
    <meta name="referrer" content="no-referrer-when-downgrade">
    

    <title>《FlutterPerformance分析工具简介》 | 早起的年轻人</title>
    <meta property="og:title" content="《FlutterPerformance分析工具简介》 - 早起的年轻人">
    <meta property="og:type" content="article">
        
    <meta property="article:published_time" content='2021-07-31T21:09:34&#43;08:00'>
        
        
    <meta property="article:modified_time" content='2021-07-31T21:09:34&#43;08:00'>
        
    <meta name="Keywords" content="Flutter，golang,go语言,go语言笔记,飞雪无情,java,android,博客,项目管理,python,软件架构,公众号,小程序">
    <meta name="description" content="《FlutterPerformance分析工具简介》">
        
    <meta name="author" content="luckly">
    <meta property="og:url" content="https://luckly.work/post/Flutter/FlutterPerformance%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7%E7%AE%80%E4%BB%8B/">
    <link rel="shortcut icon" href='/favicon.ico'  type="image/x-icon">

    <link rel="stylesheet" href='/css/normalize.css'>
    <link rel="stylesheet" href='/css/style.css'>
    <script type="text/javascript" src="//cdn.bootcdn.net/ajax/libs/jquery/3.4.1/jquery.min.js"></script>

    
    
    
        <link href="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.css" rel="stylesheet">
    
    
    
    
        <link rel="stylesheet" href='/css/douban.css'>
    
        <link rel="stylesheet" href='/css/other.css'>
    
</head>

<link rel="stylesheet"
      href="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/styles/default.min.css">
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/11.2.0/highlight.min.js"></script>
<body>
    <header id="header" class="clearfix">
    <div class="container">
        <div class="col-group">
            <div class="site-name ">
                
                    <a id="logo" href="https://luckly.work/">
                        早起的年轻人
                    </a>
                
                <p class="description">专注于Flutter、Android、Java、Go语言(golang)、移动互联网、项目管理、软件架构</p>
            </div>
            <div>
                <nav id="nav-menu" class="clearfix">
                    <a class="current" href="https://luckly.work/">首页</a>
                    
                    <a  href="https://luckly.work/categories/" title="分类">分类</a>
                    
                    <a  href="https://luckly.work/tags/" title="标签">标签</a>
                    
                    <a  href="https://luckly.work/archives/" title="归档">归档</a>
                    
                    <a  href="https://luckly.work/about/" title="关于我">关于我</a>
                    
                    <a  href="https://github.com/ITmxs/" title="github">github</a>
                    
                </nav>
            </div>
        </div>
    </div>
</header>

    <div id="body">
        <div class="container">
            <div class="col-group">

                <div class="col-8" id="main">
                    
<div class="res-cons">
    <style type="text/css">
    .post-toc {
        position: fixed;
        width: 200px;
        margin-left: -210px;
        padding: 5px 10px;
        font-family: Athelas, STHeiti, Microsoft Yahei, serif;
        font-size: 12px;
        border: 1px solid rgba(0, 0, 0, .07);
        border-radius: 5px;
        background-color: rgba(255, 255, 255, 0.98);
        background-clip: padding-box;
        -webkit-box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        box-shadow: 1px 1px 2px rgba(0, 0, 0, .125);
        word-wrap: break-word;
        white-space: nowrap;
        -webkit-box-sizing: border-box;
        box-sizing: border-box;
        z-index: 999;
        cursor: pointer;
        max-height: 70%;
        overflow-y: auto;
        overflow-x: hidden;
    }

    .post-toc .post-toc-title {
        width: 100%;
        margin: 0 auto;
        font-size: 20px;
        font-weight: 400;
        text-transform: uppercase;
        text-align: center;
    }

    .post-toc .post-toc-content {
        font-size: 15px;
    }

    .post-toc .post-toc-content>nav>ul {
        margin: 10px 0;
    }

    .post-toc .post-toc-content ul {
        padding-left: 20px;
        list-style: square;
        margin: 0.5em;
        line-height: 1.8em;
    }

    .post-toc .post-toc-content ul ul {
        padding-left: 15px;
        display: none;
    }

    @media print,
    screen and (max-width:1057px) {
        .post-toc {
            display: none;
        }
    }
</style>
<div class="post-toc" style="position: absolute; top: 188px;">
    <h2 class="post-toc-title">文章目录</h2>
    <div class="post-toc-content">
        <nav id="TableOfContents">
  <ul>
    <li><a href="#帧渲染图表">帧渲染图表</a></li>
    <li><a href="#帧事件图表">帧事件图表</a></li>
    <li><a href="#cpu-分析器">CPU 分析器</a></li>
  </ul>

  <ul>
    <li><a href="#layers">layers</a></li>
    <li><a href="#layout">layout</a></li>
    <li><a href="#animation">animation</a></li>
    <li><a href="#performance">performance</a></li>
  </ul>
</nav>
    </div>
</div>
<script type="text/javascript">
    $(document).ready(function () {
        var postToc = $(".post-toc");
        if (postToc.length) {
            var leftPos = $("#main").offset().left;
            if(leftPos<220){
                postToc.css({"width":leftPos-10,"margin-left":(0-leftPos)})
            }

            var t = postToc.offset().top - 20,
                a = {
                    start: {
                        position: "absolute",
                        top: t
                    },
                    process: {
                        position: "fixed",
                        top: 20
                    },
                };
            $(window).scroll(function () {
                var e = $(window).scrollTop();
                e < t ? postToc.css(a.start) : postToc.css(a.process)
            })
        }
    })
</script>
    <article class="post">
        <header>
            <h1 class="post-title">《FlutterPerformance分析工具简介》</h1>
        </header>
        <date class="post-meta meta-date">
            2021年7月31日
        </date>
        
        <div class="post-meta">
            <span>|</span>
            
            <span class="meta-category"><a href='/categories/Flutter'>Flutter</a></span>
            
        </div>
        
        
        <div class="post-meta">
            <span id="busuanzi_container_page_pv">|<span id="busuanzi_value_page_pv"></span><span>
                    阅读</span></span>
        </div>
        
        
        <div class="clear" style="display: none">
            <div class="toc-article">
                <div class="toc-title">文章目录</div>
            </div>
        </div>
        
        <div class="post-content">
            <blockquote>
<p>Flutter 提供了不少性能分析工具，但感觉相关文档不咋的，散落在官方的各个地方，对开发者不太友好。另外，有的工具目前只在 Android Studio 中有，比如 Flutter Performance；甚至有的工具只在 debug 模式下可用。本文对这些工具简单整理一下，便于做性能优化时查找和参考。</p>
</blockquote>
<h1 id="performance-overlay">Performance Overlay</h1>
<p>开启 Performance Overlay 有多种方式，最简单的几种包括：</p>
<ul>
<li>Android Studio &gt; Flutter Inspector &gt; Performance Overlay</li>
<li>Android Studio &gt; Flutter Performance &gt; Performance Overlay</li>
<li>DevTools &gt; Timeline &gt; Performance Overlay</li>
</ul>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786503018684.jpg">
            <img class="mx-auto" alt="-w477" src="https://www.sunmoonblog.com/images/15786503018684.jpg" />
        </a>
    </p>
<p>性能图层用两张图表显示应用的耗时信息。每一张图表都代表当前线程的最近 300 帧表现。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786490815418.jpg">
            <img class="mx-auto" alt="img" src="https://www.sunmoonblog.com/images/15786490815418.jpg" />
        </a>
    </p>
<ul>
<li>顶部的图形表示 GPU 线程所花费的时间</li>
<li>底部的图表显示了 UI 线程所花费的时间</li>
<li>竖轴表示耗时，沿竖轴的黑线是时间线 (间隔单位为 16ms)</li>
<li>横轴则表示帧，垂直的绿色条代表的是当前帧</li>
<li>卡顿时绿色条会变成红色条
<ul>
<li>如果是在 UI 图表出现了红色竖条，则表明 Dart 代码消耗了大量资源</li>
<li>而如果红色竖条是在 GPU 图表出现的，意味着场景太复杂导致无法快速渲染</li>
</ul>
</li>
</ul>
<p>更多信息请参考 <a href="https://flutter.dev/docs/perf/rendering/ui-performance#flutters-threads">Flutter 线程</a></p>
<p>使用 Performance Overlay 可以对 UI 性能问题进行<strong>定性分析</strong>，大致判断到底是 Dart 代码执行过慢(布局慢)还是场景复杂无法快速渲染(渲染慢)。</p>
<p>Performance Overlay 可用于 profile 模式。</p>
<h1 id="performanceoverlay控件httpsapiflutterdevflutterwidgetsperformanceoverlay-classhtml"><a href="https://api.flutter.dev/flutter/widgets/PerformanceOverlay-class.html">PerformanceOverlay控件</a></h1>
<p><a href="https://api.flutter.dev/flutter/widgets/PerformanceOverlay-class.html">PerformanceOverlay</a> 可以视为 Performance Overlay 的高级版本(Performance Overlay 正是基于 PerformanceOverlay 控件来实现的)。</p>
<p>通过如下方式在代码中开启 <code>PerformanceOverlay</code> 控件。<a href="https://flutter.dev/docs/testing/code-debugging#performance-overlay">参考</a>。</p>
<pre><code>class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      showPerformanceOverlay: true,
      title: 'My Awesome App',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: MyHomePage(title: 'My Awesome App'),
    );
  }
}
</code></pre><p>如果没有使用 <code>MaterialApp</code> 等控件，可以自己调用 <code>PerformanceOverlay.allEnabled(checkerboardOffscreenLayers: true,);</code> 来实现类似效果。</p>
<h1 id="observatoryhttpsdart-langgithubioobservatory-之-timeline"><a href="https://dart-lang.github.io/observatory/">Observatory</a> 之 Timeline</h1>
<p>Observatory 是 Dart SDK 提供的用于分析和调试 Dart 程序的工具。可以使用 Observatory 来观察 Dart VM 内部状态，获取应用的实时数据。主要功能包括：</p>
<ul>
<li>检查应用的耗时情况</li>
<li>检查已分配内存</li>
<li>检查哪些代码已执行</li>
<li>调试内存泄漏问题</li>
<li>调试内存碎片问题</li>
</ul>
<p>虽然 Observatory 正在被 DevTools 慢慢取代，但某些情况下它提供的性能数据更为详细。</p>
<p>Observatory 的使用步骤：</p>
<ol>
<li>VS Code 或命令行下打开 Observatory</li>
<li>点击 timeline</li>
<li>点击 Flutter Developer</li>
<li>操作应用</li>
<li>点击 Refresh 加载数据</li>
<li>w/s 放大， a/d (点?号可以看到全部的快捷键)</li>
</ol>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15813940478063.jpg">
            <img class="mx-auto" alt="img" src="https://www.sunmoonblog.com/images/15813940478063.jpg" />
        </a>
    </p>
<p>刷新后可以在事件面板中检查和分析UI线程和GPU的耗时，以定位性能瓶颈。</p>
<ul>
<li>将 <code>debugProfileBuildsEnabled</code> 设置为 <code>true</code> 可以在 Observatory 中看到 构建 Widget 的耗时</li>
<li>Save 后导出的 json 文件可以重新导入 Chrome 进行分析。Chrome 中输入 <code>chrome://tracing</code> 然后将 json 文件拖进去</li>
</ul>
<h1 id="devtools-之-timeline">DevTools 之 Timeline</h1>
<p><a href="https://flutter.dev/docs/development/tools/devtools/timeline#frame-rendering-chart">时间线视图</a>用于显示 Flutter 帧信息。它由三个部分组成。</p>
<ul>
<li>帧渲染图表</li>
<li>帧事件图表</li>
<li>CPU 分析器</li>
</ul>
<p>使用 Timeline 可以对 UI 性能问题进行<strong>定量分析</strong>，通过观察布局阶段和渲染阶段的耗时，进一步定位问题原因。</p>
<p>Performance Overlay 可用于 profile 模式。</p>
<h2 id="帧渲染图表">帧渲染图表</h2>
<p>帧渲染图表跟 Performance Overlay 很类似。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786578717563.jpg">
            <img class="mx-auto" alt="img" src="https://www.sunmoonblog.com/images/15786578717563.jpg" />
        </a>
    </p>
<p>图表中的每个条形框都代表一帧，每帧中不同线程的执行情况以不同颜色表示。</p>
<ul>
<li>UI 线程执行 Dart VM 中的 Dart 代码。构建过于复杂的图层树可能导致这个线程变慢</li>
<li>GPU 线程执行 Flutter 引擎中图形相关的代码。某些图层树易于构建却难于渲染，也可能导致这个线程变慢</li>
</ul>
<h2 id="帧事件图表">帧事件图表</h2>
<p>在帧渲染图表中选中一帧后，帧事件图表中将显示具体事件及其耗时。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786583559211.jpg">
            <img class="mx-auto" alt="-w1274" src="https://www.sunmoonblog.com/images/15786583559211.jpg" />
        </a>
    </p>
<ul>
<li><a href="https://api.flutter.dev/flutter/widgets/debugProfileBuildsEnabled.html">debugProfileBuildsEnabled</a> - 向 Timeline 事件中添加 build 信息</li>
<li><a href="https://api.flutter.dev/flutter/rendering/debugProfilePaintsEnabled.html">debugProfilePaintsEnabled</a> - 向 timeline 事件中添加 paint 信息</li>
<li><a href="https://api.flutter.dev/flutter/widgets/debugPrintRebuildDirtyWidgets.html">debugPrintRebuildDirtyWidgets</a> - 记录每帧重建的 widget</li>
</ul>
<h2 id="cpu-分析器">CPU 分析器</h2>
<ul>
<li>采样率
<ul>
<li>高采样率 - 单元时间内采集的 CPU 信息会更加详细且采集样例更多。但应用性能可能下降，采样存储空间可能溢出</li>
<li>单元时间内采集的 CPU 信息会比较粗略且采集样例较少。对应用性能影响小，可以采集更长时间</li>
</ul>
</li>
<li>图表
<ul>
<li>火焰图 - 展示的是自上而下的调用堆栈信息，即上面的堆栈帧调用下面的堆栈帧。每一个堆<strong>栈帧的宽度代表 CPU 执行的时长</strong>。调用堆栈栈帧消耗 CPU 的时间越长，就越洽有可能是我们进行性能改进的好地方</li>
<li>调用树 - 展示的是自上而下展示 CPU 中的调用堆栈信息</li>
<li>Bottom up 视图 - 用于显示方法调用堆栈，是一个自下而上的表示方式。表格中的每个最上方的方法实际上是给定 CPU 样本的调用堆栈中的最后一个方法</li>
</ul>
</li>
</ul>
<h1 id="chrome-tracing">Chrome Tracing</h1>
<p>我们可以从 DevTools Timeline 中导出 timeline 文件。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786557953993.jpg">
            <img class="mx-auto" alt="-w1000" src="https://www.sunmoonblog.com/images/15786557953993.jpg" />
        </a>
    </p>
<p>导出的 timeline 文件可以重新导入到 chrome tracing 进行分析。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786559387247.jpg">
            <img class="mx-auto" alt="-w1000" src="https://www.sunmoonblog.com/images/15786559387247.jpg" />
        </a>
    </p>
<p>chrome tracing 几个常用的操作键包括：</p>
<ul>
<li>W - 放大</li>
<li>S - 缩小</li>
<li>A - 左移</li>
<li>D - 右移</li>
</ul>
<p>chrome tracing 工具展示如下两个阶段的耗时：</p>
<ul>
<li>VSYNC</li>
<li>GPURasterizer:Draw</li>
</ul>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786563521810.jpg">
            <img class="mx-auto" alt="-w1147" src="https://www.sunmoonblog.com/images/15786563521810.jpg" />
        </a>
    </p>
<p>(TODO 如何解读这些数据? 比 CPU 分析器更容易观察数据?)</p>
<p><a href="https://api.flutter.dev/flutter/dart-developer/Timeline-class.html">Timeline</a> 用于向时间线添加同步事件。使用方法很简单：</p>
<pre><code>Timeline.startSync(&quot;Doing Something&quot;);
doSomething();
Timeline.finishSync();
</code></pre><p>或者：</p>
<pre><code>Timeline.timeSync(&quot;Doing Something&quot;, () {
  doSomething();
});
</code></pre><p>我们在代码中添加 “Doing Something”，</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15790537579215.jpg">
            <img class="mx-auto" alt="-w519" src="https://www.sunmoonblog.com/images/15790537579215.jpg" />
        </a>
    </p>
<p>然后将 DevTools Timeline 导出的 timeline 文件重新导入到 Chrome Tracing 工具。从中我们可以找到 “Doing Something” 对应的事件，如下图：</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15790539789634.jpg">
            <img class="mx-auto" alt="-w900" src="https://www.sunmoonblog.com/images/15790539789634.jpg" />
        </a>
    </p>
<h1 id="widget-rebuild-profilerhttpsfluttercndocsdevelopmenttoolsandroid-studioshow-performance-data"><a href="https://flutter.cn/docs/development/tools/android-studio#show-performance-data">Widget rebuild profiler</a></h1>
<p>Android Studio 中 View &gt; Tool Windows &gt; Flutter Performance 打开性能工具窗口，在 Widget rebuild stats 中勾选 Track widget rebuilds 来查看 widget 的重建信息。重建信息包括 Widget 名字、源码位置、上一帧中重建次数、当前页面中重建次数。此外，Widget 名字前面还会显示一个小图标。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15788975395660.jpg">
            <img class="mx-auto" alt="-w697" src="https://www.sunmoonblog.com/images/15788975395660.jpg" />
        </a>
    </p>
<ul>
<li>黄色旋转圆圈 - 重建次数过多</li>
<li>灰色圆圈 - 未重建</li>
<li>灰色旋转圆圈 其他情况</li>
</ul>
<p>这个功能的目的是让你了解 widget 是何时重建的，如果发生不符合预期的重建，就需要优化代码了。优化方法请参考 <a href="https://api.flutter.dev/flutter/widgets/StatefulWidget-class.html#performance-considerations">StatefulWidget 与性能</a> (译文见<a href="https://www.sunmoonblog.com/2020/01/10/stateful-widget-performance-considerations/">这里</a>)</p>
<p>Widget rebuild profiler 只能用于 debug 模式。</p>
<h1 id="fps">FPS</h1>
<p>Performance Overlay 使用两张图来表示 UI线程 和 GPU线程的最近 300 帧表现。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15786490815418.jpg">
            <img class="mx-auto" alt="img" src="https://www.sunmoonblog.com/images/15786490815418.jpg" />
        </a>
    </p>
<p>不过 FPS 对我们来说更直接。Android Studio Flutter Performance 中可以看到 FPS 值：</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15788855830332.jpg">
            <img class="mx-auto" alt="-w703" src="https://www.sunmoonblog.com/images/15788855830332.jpg" />
        </a>
    </p>
<p>我们也可以使用 <code>WidgetsBinding.addTimingsCallback</code> 方法来自行统计 FPS。这里提供两个参考实现：</p>
<ul>
<li><a href="https://gist.github.com/yrom/ac4f30b26ee02ce3bd3a1d260bb9ffb4">统计FPS</a></li>
<li><a href="https://gist.github.com/410063005/3293c1faa78a01a3d0e7b4e2ce12d1af">FpsWidget</a></li>
</ul>
<h1 id="测试参数httpsflutterdevdocstestingcode-debugging"><a href="https://flutter.dev/docs/testing/code-debugging">测试参数</a></h1>
<p>刚入门 Flutter 开发时，你肯定会如何右上角那个刺眼的 debug 标志苦恼过。</p>
<p>
        <a data-fancybox="gallery" href="https://www.sunmoonblog.com/images/15789021349152.jpg">
            <img class="mx-auto" alt="Debug logo -w320" src="https://www.sunmoonblog.com/images/15789021349152.jpg" />
        </a>
    </p>
<p>方法很简单。将 <code>debugShowCheckedModeBanner</code> 参数设置为 <code>false</code> 即可。</p>
<pre><code>MaterialApp(
 debugShowCheckedModeBanner: false
)
</code></pre><p>Flutter 提供性能测试/调试参数，这些参数通常是布尔类型，只要在代码中打开相应的参数就可以开始进行性能测试。</p>
<ul>
<li><a href="https://api.flutter-io.cn/flutter/rendering/PerformanceOverlayLayer/checkerboardOffscreenLayers.html">PerformanceOverlayLayer.checkerboardOffscreenLayers</a> 用于检查是否使用 <code>saveLayer</code>，详情请参考 <a href="https://flutter.dev/docs/perf/rendering/ui-performance#checking-for-offscreen-layers">Checking for offscreen layers</a></li>
<li><a href="https://api.flutter-io.cn/flutter/rendering/PerformanceOverlayLayer/checkerboardRasterCacheImages.html">PerformanceOverlayLayer.checkerboardRasterCacheImages</a> 用于检查哪些图片被缓存，请情请参考 <a href="https://flutter.dev/docs/perf/rendering/ui-performance#checking-for-non-cached-images">Checking for non-cached images</a></li>
</ul>
<pre><code>MaterialApp(
  checkerboardOffscreenLayers: true,
  checkerboardRasterCacheImages: true,
)
</code></pre><h1 id="debug-flags">Debug flags</h1>
<h2 id="layers">layers</h2>
<p>Flutter framework 的每一层都提供了函数来输出当前状态或事件到控制台(这些函数调用 <code>debugPrint</code>)。</p>
<p>调用 <a href="https://api.flutter-io.cn/flutter/widgets/debugDumpApp.html">debugDumpApp()</a> 输出 the state of the Widgets library。不应在 <code>build()</code> 方法中调用 <code>debugDumpApp()</code>，可以在调用 <code>runApp()</code> 后的任何时候调用 <code>debugDumpApp()</code>。调用 <a href="https://api.flutter-io.cn/flutter/widgets/Widget/debugFillProperties.html">debugFillProperties()</a> 方法向 <code>debugDumpApp()</code> 的输出添加自定义信息。</p>
<p>调用 <a href="https://api.flutter-io.cn/flutter/rendering/debugDumpRenderTree.html">debugDumpRenderTree()</a> 方法来输出 rendering tree，用于分析布局问题。建议在 <a href="https://api.flutter-io.cn/flutter/scheduler/SchedulerBinding/addPersistentFrameCallback.html">frame callback</a> 或 event handler 中调用 <code>debugDumpRenderTree()</code> 方法。分析布局问题时，关注的关键字段是 <code>size</code> 和 <code>constraints</code>。调用 <a href="https://api.flutter-io.cn/flutter/rendering/Layer/debugFillProperties.html">debugFillProperties()</a> 方法向 <code>debugDumpRenderTree()</code> 的输出添加自定义信息。</p>
<p>调用 <a href="https://api.flutter-io.cn/flutter/rendering/debugDumpLayerTree.html">debugDumpLayerTree()</a> 方法来输出 layer tree，用于分析 compositing 问题。</p>
<blockquote>
<p>The RepaintBoundary widget, which creates a RenderRepaintBoundary in the render tree, creates a new layer in the layer tree. This is used to reduce how much needs to be repainted.</p>
</blockquote>
<p>可以使用 <code>RepaintBoundary</code> 来在 render tree 中创建 <code>RenderRepaintBoundary</code> ，即，在 layer tree 中创建新的 layer。这种方法可以减少重绘工作。详细可参考 <a href="https://juejin.im/post/5deda528f265da339f7ce93c">说说Flutter中的RepaintBoundary - 掘金</a>。</p>
<p>调用 <a href="https://api.flutter.dev/flutter/rendering/debugDumpSemanticsTree.html">debugDumpSemanticsTree()</a> 方法来输出 semantics tree (这棵树表示 system accessibility APIs)。暂时用不上，略过。</p>
<p>调用 <a href="https://api.flutter.dev/flutter/scheduler/debugPrintBeginFrameBanner.html">debugPrintBeginFrameBanner</a> 和 <a href="https://api.flutter.dev/flutter/scheduler/debugPrintEndFrameBanner.html">debugPrintEndFrameBanner</a> 方法来输出一帧的开始和结束。</p>
<pre><code>void main() {
  runApp(DemoApp());
  debugPrintBeginFrameBanner = true;
  debugPrintEndFrameBanner = true;
}
</code></pre><h2 id="layout">layout</h2>
<p><a href="https://api.flutter.dev/flutter/rendering/debugPaintSizeEnabled.html">debugPaintSizeEnabled</a> 用于调试布局问题。其用法如下：</p>
<pre><code>void main() {
    debugPaintSizeEnabled = true;
    runApp(DemoApp());
}
</code></pre><ul>
<li>box - 所有的 box 外都显示一个亮蓝绿色边界</li>
<li>padding - 以浅蓝色显示 <code>Padding</code> 等控件 (带一个深蓝色 box)</li>
<li>alignment - 包括 <code>Center</code> 和 <code>Align</code> 等控件，以黄色箭头显示</li>
<li>spacer - 以灰色显示，比如没有子节点的 <code>Container</code> 就属于这一类</li>
</ul>
<p><a href="https://api.flutter.dev/flutter/rendering/debugPaintBaselinesEnabled.html">debugPaintBaselinesEnabled</a> 的作用类似，它显示的是对象的基线。</p>
<p><a href="https://api.flutter.dev/flutter/rendering/debugPaintPointersEnabled.html">debugPaintPointersEnabled</a> 用于开启一个特殊的模式：该模式下被点击的对象以蓝绿色显示。这个功能用于检查 hit test 是否正确。</p>
<p>还有几个用于调试 compositor layer 的 flag，</p>
<ul>
<li><a href="https://api.flutter.dev/flutter/rendering/debugPaintLayerBordersEnabled.html">debugPaintLayerBordersEnabled</a> - 以橙色显示每个 layer 的边界，用于检查是否需要使用 <code>RepaintBoundary</code> 控件</li>
<li><a href="https://api.flutter.dev/flutter/rendering/debugRepaintRainbowEnabled.html">debugRepaintRainbowEnabled</a> - 每个 layer 重绘时会叠加上不同的颜色。使用技巧：如果一个静态的 widget 颜色出现变化，可以考虑给它加上 <code>RepaintBoundary</code></li>
<li>debugPrintScheduleBuildForStacks - 为什么被构建</li>
<li>debugPrintRebuildDirtyWidgets - 什么组件被重新构建了</li>
<li>debugProfileBuildsEnabled - 在观测台里显示构建树</li>
<li><a href="https://api.flutter.dev/flutter/rendering/debugPaintLayerBordersEnabled.html">debugPaintLayerBordersEnabled</a> - 查看 layer 界线</li>
<li><a href="https://api.flutter.dev/flutter/widgets/debugProfileBuildsEnabled.html">debugProfileBuildsEnabled</a> - Adds Timeline events for every Widget built.</li>
<li><a href="https://api.flutter.dev/flutter/rendering/debugProfilePaintsEnabled.html">debugProfilePaintsEnabled</a></li>
<li>debugPrintRebuildDirtyWidgets
<ul>
<li>结合 <a href="https://api.flutter.dev/flutter/widgets/debugPrintScheduleBuildForStacks.html">debugPrintScheduleBuildForStacks</a>，可以观察 widget 的 dirty/clean 生命周期</li>
<li>结合 <a href="https://api.flutter.dev/flutter/widgets/debugProfileBuildsEnabled.html">debugProfileBuildsEnabled</a>，可以在 DevTools Timeline 中观察到详细事件信息</li>
</ul>
</li>
</ul>
<p>注意：所有这些以 debug 开头的 flag 均只能工作于 debug 模式。</p>
<h2 id="animation">animation</h2>
<p>调试动画的最有效方式是减慢其速度。可以使用 DevTool 中 <a href="https://flutter.dev/docs/development/tools/devtools/inspector">Inspector view</a> 的 Slow Animations 按钮来减慢。可以使用 <a href="https://api.flutter.dev/flutter/scheduler/timeDilation.html">timeDilation</a> 来更精确地控制动画速度。</p>
<h2 id="performance">performance</h2>
<p><a href="https://api.flutter.dev/flutter/rendering/debugPrintMarkNeedsLayoutStacks.html">debugPrintMarkNeedsLayoutStacks</a> - 如果 layout 次数比预期中的要多，可以通过这个 flag 来观察 render box 被置为 dirty 的原因。</p>
<h1 id="flutter-driver">Flutter Driver</h1>
<p>TODO</p>
<ul>
<li><a href="https://flutter.cn/docs/perf/rendering/ui-performance#benchmarking">https://flutter.cn/docs/perf/rendering/ui-performance#benchmarking</a></li>
</ul>
<h1 id="一些小技巧">一些小技巧</h1>
<ul>
<li>检查 Performance Overlay</li>
<li>检查 FPS (自行计算 FPS)</li>
<li>检查屏幕之外的视图 (使用 <code>checkerboardOffscreenLayers</code>)</li>
<li>检查没有缓存的图像 (使用 <code>checkerboardRasterCacheImages</code>)</li>
<li>检查 widget 重建性能 (使用 Widget rebuild stats)</li>
</ul>
<p>优化点：</p>
<ul>
<li>想办法减少 widget 重建</li>
</ul>
<h1 id="参考">参考</h1>
<ul>
<li><a href="https://flutter.dev/docs/testing/code-debugging">code-debugging</a></li>
<li><a href="https://flutter.dev/docs/testing/debugging">debugging</a></li>
<li><a href="https://flutter.dev/docs/perf/rendering/ui-performance">ui-performance</a></li>
<li><a href="https://medium.com/flutter/performance-testing-of-flutter-apps-df7669bb7df7">Performance testing of Flutter apps - Flutter - Medium</a></li>
</ul>
        </div>

        
<div class="post-archive">
    <ul class="post-copyright">
        <li><strong>原文作者：</strong><a rel="author" href="https://luckly.work/">luckly</a></li>
        <li style="word-break:break-all"><strong>原文链接：</strong><a href="https://luckly.work/post/Flutter/FlutterPerformance%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7%E7%AE%80%E4%BB%8B/">https://luckly.work/post/Flutter/FlutterPerformance%E5%88%86%E6%9E%90%E5%B7%A5%E5%85%B7%E7%AE%80%E4%BB%8B/</a></li>
        <li><strong>版权声明：</strong>本作品采用<a rel="license" href="https://creativecommons.org/licenses/by-nc-nd/4.0/">知识共享署名-非商业性使用-禁止演绎 4.0 国际许可协议</a>进行许可，非商业转载请注明出处（作者，原文链接），商业转载请联系作者获得授权。</li>
    </ul>
</div>
<br/>



        

<div class="post-archive">
    <h2>See Also</h2>
    <ul class="listing">
        
        <li><a href="/post/Flutter/Flutter%E4%B9%8BStatefulWidget%E4%B8%8E%E6%80%A7%E8%83%BD/">《Flutter之StatefulWidget与性能》</a></li>
        
        <li><a href="/post/Flutter/Flutter%E4%B9%8BRenderObject%E6%B5%85%E6%9E%90/">《Flutter之RenderObject浅析》</a></li>
        
        <li><a href="/post/dart/Dart%E4%B9%8BMixins/">《Dart之Mixins》</a></li>
        
        <li><a href="/post/Flutter/Flutter%E4%B9%8BRenderObject%E4%BB%8B%E7%BB%8D/">《Flutter之RenderObject介绍》</a></li>
        
        <li><a href="/post/dart/Dart%E5%BC%82%E6%AD%A5%E7%BC%96%E7%A8%8B%E4%B9%8BIsolate%E5%92%8C%E4%BA%8B%E4%BB%B6%E5%BE%AA%E7%8E%AF/">《Dart异步编程之Isolate和事件循环》</a></li>
        
    </ul>
</div>


        <div class="post-meta meta-tags">
            
            <ul class="clearfix">
                
                <li><a href='/tags/Flutter'>Flutter</a></li>
                
            </ul>
            
        </div>
    </article>
    
    

    
    
    <div class="post bg-white">
      <script src="https://utteranc.es/client.js"
            repo= "https://github.com/ITmxs/repo"
            issue-term="pathname"
            theme="github-light"
            crossorigin="anonymous"
            async>
      </script>
    </div>
    
</div>

                    <footer id="footer">
    <div>
        &copy; 2021 <a href="https://luckly.work/">早起的年轻人 By luckly</a>
        
        | <a rel="nofollow" target="_blank" href="http://beian.miit.gov.cn/">粤ICP备2021号-1</a>
        
    </div>
    <br />
    <div>
        <div class="github-badge">
            <a href="https://juejin.cn/user/3843548384077192" target="_black" rel="nofollow"><span class="badge-subject">Powered by</span><span class="badge-value bg-blue">掘金</span></a>
        </div>
        <div class="github-badge">
            <a href="https://space.bilibili.com/480883651" target="_black"><span class="badge-subject">Design by</span><span class="badge-value bg-brightgreen">早起的年轻人</span></a>
        </div>
        <div class="github-badge">
            <a href="https://cloud.tencent.com/developer/user/6702670" target="_black"><span class="badge-subject">Theme</span><span class="badge-value bg-yellowgreen">云社区</span></a>
        </div>
    </div>
</footer>


    
    <script type="text/javascript">
        window.MathJax = {
            tex2jax: {
                inlineMath: [['$', '$']],
                processEscapes: true
                }
            };
    </script>
    <script src='https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-MML-AM_CHTML' async></script><script src="https://cdn.bootcdn.net/ajax/libs/fancybox/3.5.7/jquery.fancybox.min.js"></script>

<a id="rocket" href="#top"></a>
<script type="text/javascript" src='/js/totop.js?v=0.0.0' async=""></script>



    <script type="text/javascript" src="//busuanzi.ibruce.info/busuanzi/2.3/busuanzi.pure.mini.js" async></script>




    <script src='/js/douban.js'></script>
    <script src="/js/copy-to-clipboard.js"></script>

                </div>

                <div id="secondary">
    <section class="widget">
        <form id="search" action='https://luckly.work/search/' method="get" accept-charset="utf-8" target="_blank" _lpchecked="1">
      
      <input type="text" name="q" maxlength="20" placeholder="Search">
      <input type="hidden" name="sitesearch" value="https://luckly.work/">
      <button type="submit" class="submit icon-search"></button>
</form>
    </section>
    
    <section class="widget">
        <h3 class="widget-title">最近文章</h3>
<ul class="widget-list">
    
    <li>
        <a href="https://luckly.work/post/nginx/nginx%E6%96%87%E4%BB%B6%E5%86%85%E5%AE%B9/" title="Nginx文件内容">Nginx文件内容</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/nginx/nginx%E6%9E%81%E7%AE%80%E6%95%99%E7%A8%8B/" title="Nginx极简教程">Nginx极简教程</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/nginx/%E5%8D%81%E5%88%86%E9%92%9F%E5%85%A5%E9%97%A8nginx/" title="十分钟入门Nginx">十分钟入门Nginx</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/go/Goland%E8%BF%9C%E7%A8%8B%E5%BC%80%E5%8F%91%E9%85%8D%E7%BD%AE/" title="Goland远程开发配置">Goland远程开发配置</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E8%AF%BB%E4%B9%A6/%E5%9F%9F%E5%90%8D%E8%A7%A3%E6%9E%90/" title="域名解析">域名解析</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/git/%E6%8F%90%E4%BA%A4%E8%BF%87%E7%A8%8B%E7%9C%81%E7%95%A5%E6%9F%90%E4%BA%9B%E6%96%87%E4%BB%B6/" title="提交过程省略某些文件">提交过程省略某些文件</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter_DropdownButton%E7%A4%BA%E4%BE%8B/" title="Flutter_DropdownButton示例">Flutter_DropdownButton示例</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter_ExpansionPanelList%E5%92%8CExpansionPanelList.radio%E7%A4%BA%E4%BE%8B/" title="Flutter_ExpansionPanelList和ExpansionPanelList">Flutter_ExpansionPanelList和ExpansionPanelList</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/flutter_tips/Flutter%E5%BE%AE%E4%BF%A1%E5%88%86%E4%BA%AB%E9%93%BE%E6%8E%A5%E8%B7%B3%E5%9B%9EApp%E6%8C%87%E5%AE%9A%E9%A1%B5%E9%9D%A2/" title="Flutter微信分享链接跳回App指定页面">Flutter微信分享链接跳回App指定页面</a>
    </li>
    
    <li>
        <a href="https://luckly.work/post/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F/%E5%A4%96%E5%8C%85%E5%8F%AF%E8%83%BD%E7%9A%84%E9%97%AE%E9%A2%98/" title="外包可能的问题">外包可能的问题</a>
    </li>
    
</ul>
    </section>

    

    <section class="widget">
        <h3 class="widget-title"><a href='/categories/'>分类</a></h3>
<ul class="widget-list">
    
    <li><a href="https://luckly.work/categories/Flutter/">Flutter (326)</a></li>
    
    <li><a href="https://luckly.work/categories/IT/">IT (2)</a></li>
    
    <li><a href="https://luckly.work/categories/Kotlin/">Kotlin (2)</a></li>
    
    <li><a href="https://luckly.work/categories/Mysql/">Mysql (1)</a></li>
    
    <li><a href="https://luckly.work/categories/nginx/">nginx (1)</a></li>
    
    <li><a href="https://luckly.work/categories/Vue/">Vue (6)</a></li>
    
    <li><a href="https://luckly.work/categories/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/android/">android (6)</a></li>
    
    <li><a href="https://luckly.work/categories/dart/">dart (96)</a></li>
    
    <li><a href="https://luckly.work/categories/Flutter/">Flutter (28)</a></li>
    
    <li><a href="https://luckly.work/categories/gin/">gin (25)</a></li>
    
    <li><a href="https://luckly.work/categories/git/">git (4)</a></li>
    
    <li><a href="https://luckly.work/categories/Go/">Go (102)</a></li>
    
    <li><a href="https://luckly.work/categories/gorm/">gorm (4)</a></li>
    
    <li><a href="https://luckly.work/categories/grpc/">grpc (1)</a></li>
    
    <li><a href="https://luckly.work/categories/html/">html (3)</a></li>
    
    <li><a href="https://luckly.work/categories/ios/">ios (1)</a></li>
    
    <li><a href="https://luckly.work/categories/linux/">linux (1)</a></li>
    
    <li><a href="https://luckly.work/categories/nginx/">nginx (6)</a></li>
    
    <li><a href="https://luckly.work/categories/python/">python (35)</a></li>
    
    <li><a href="https://luckly.work/categories/read/">读书笔记 (6)</a></li>
    
    <li><a href="https://luckly.work/categories/redis/">redis (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E5%8D%95/">书单 (8)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%B9%A6%E8%AF%84/">书评 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师 (19)</a></li>
    
    <li><a href="https://luckly.work/categories/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师 (25)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E5%88%99/">原则 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%9F%BA%E7%A1%80/">基础 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E5%BF%83%E8%AF%AD/">心语 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%8F%92%E4%BB%B6/">插件 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E6%95%99%E5%AD%A6/">教学 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%B2%BE%E8%BF%9B/">精进 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E7%BC%96%E7%A8%8B/">编程 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%99%9A%E5%B9%BB/">虚幻 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路 (2)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%91%E6%AD%A5/">跑步 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%B7%AF%E7%BA%BF/">路线 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学 (3)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%A1%B9%E7%9B%AE/">项目 (1)</a></li>
    
    <li><a href="https://luckly.work/categories/%E9%AD%85%E5%8A%9B/">魅力 (1)</a></li>
    
</ul>
    </section>

    <section class="widget">
        <h3 class="widget-title"><a href='/tags/'>标签</a></h3>
<div class="tagcloud">
    
    <a href="https://luckly.work/tags/flutter/">flutter</a>
    
    <a href="https://luckly.work/tags/IT/">IT</a>
    
    <a href="https://luckly.work/tags/Kotlin/">Kotlin</a>
    
    <a href="https://luckly.work/tags/Mysql/">Mysql</a>
    
    <a href="https://luckly.work/tags/nginx/">nginx</a>
    
    <a href="https://luckly.work/tags/Vue/">Vue</a>
    
    <a href="https://luckly.work/tags/YouTube%E8%A7%86%E9%A2%91%E4%B8%8B%E8%BD%BD/">YouTube视频下载</a>
    
    <a href="https://luckly.work/tags/android/">android</a>
    
    <a href="https://luckly.work/tags/dart/">dart</a>
    
    <a href="https://luckly.work/tags/flutter/">flutter</a>
    
    <a href="https://luckly.work/tags/gin/">gin</a>
    
    <a href="https://luckly.work/tags/git/">git</a>
    
    <a href="https://luckly.work/tags/go/">go</a>
    
    <a href="https://luckly.work/tags/gorm/">gorm</a>
    
    <a href="https://luckly.work/tags/grpc/">grpc</a>
    
    <a href="https://luckly.work/tags/html/">html</a>
    
    <a href="https://luckly.work/tags/ios/">ios</a>
    
    <a href="https://luckly.work/tags/linux/">linux</a>
    
    <a href="https://luckly.work/tags/nginx/">nginx</a>
    
    <a href="https://luckly.work/tags/python/">python</a>
    
    <a href="https://luckly.work/tags/redis/">redis</a>
    
    <a href="https://luckly.work/tags/%E4%B8%AA%E4%BA%BA%E8%B5%84%E6%96%99/">个人资料</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E5%8D%95/">书单</a>
    
    <a href="https://luckly.work/tags/%E4%B9%A6%E8%AF%84/">书评</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统管理师</a>
    
    <a href="https://luckly.work/tags/%E4%BF%A1%E6%81%AF%E7%B3%BB%E7%BB%9F%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E5%B8%88/">信息系统项目管理师</a>
    
    <a href="https://luckly.work/tags/%E5%85%A5%E9%97%A8/">入门</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E5%88%99/">原则</a>
    
    <a href="https://luckly.work/tags/%E5%8E%9F%E7%94%9F%E9%80%9A%E8%AE%AF/">原生通讯</a>
    
    <a href="https://luckly.work/tags/%E5%9F%BA%E7%A1%80/">基础</a>
    
    <a href="https://luckly.work/tags/%E5%A4%8D%E5%88%A9%E6%95%88%E5%BA%94/">复利效应</a>
    
    <a href="https://luckly.work/tags/%E5%AE%89%E8%A3%85%E6%95%99%E7%A8%8B/">安装教程</a>
    
    <a href="https://luckly.work/tags/%E5%B0%91%E6%9C%89%E4%BA%BA%E8%B5%B0%E7%9A%84%E8%B7%AF/">少有人走的路</a>
    
    <a href="https://luckly.work/tags/%E5%BF%83%E8%AF%AD/">心语</a>
    
    <a href="https://luckly.work/tags/%E6%8F%92%E4%BB%B6/">插件</a>
    
    <a href="https://luckly.work/tags/%E6%95%99%E5%AD%A6/">教学</a>
    
    <a href="https://luckly.work/tags/%E7%8E%8B%E9%98%B3%E6%98%8E/">王阳明</a>
    
    <a href="https://luckly.work/tags/%E7%94%B5%E5%AD%90%E4%B9%A6/">电子书</a>
    
    <a href="https://luckly.work/tags/%E7%99%BB%E9%99%86%E8%A1%A8%E5%8D%95/">登陆表单</a>
    
    <a href="https://luckly.work/tags/%E7%A8%BB%E7%9B%9B%E5%92%8C%E5%A4%AB/">稻盛和夫</a>
    
    <a href="https://luckly.work/tags/%E7%A9%B7%E7%88%B8%E7%88%B8%E5%AF%8C%E7%88%B8%E7%88%B8/">穷爸爸富爸爸</a>
    
    <a href="https://luckly.work/tags/%E7%B2%BE%E8%BF%9B/">精进</a>
    
    <a href="https://luckly.work/tags/%E7%BC%96%E7%A8%8B/">编程</a>
    
    <a href="https://luckly.work/tags/%E8%99%9A%E5%B9%BB/">虚幻</a>
    
    <a href="https://luckly.work/tags/%E8%AF%97/">诗</a>
    
    <a href="https://luckly.work/tags/%E8%AF%BB%E4%B9%A6%E7%AC%94%E8%AE%B0/">读书笔记</a>
    
    <a href="https://luckly.work/tags/%E8%B4%A2%E5%8A%A1%E8%87%AA%E7%94%B1%E4%B9%8B%E8%B7%AF/">财务自由之路</a>
    
    <a href="https://luckly.work/tags/%E8%B7%91%E6%AD%A5/">跑步</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%94%B1%E4%BC%A0%E5%8F%82/">路由传参</a>
    
    <a href="https://luckly.work/tags/%E8%B7%AF%E7%BA%BF/">路线</a>
    
    <a href="https://luckly.work/tags/%E8%BD%AF%E4%BB%B6%E5%AE%9E%E6%96%BD/">软件实施</a>
    
    <a href="https://luckly.work/tags/%E9%80%9A%E8%AE%AF%E5%BD%95/">通讯录</a>
    
    <a href="https://luckly.work/tags/%E9%98%B3%E6%98%8E%E5%BF%83%E5%AD%A6/">阳明心学</a>
    
    <a href="https://luckly.work/tags/%E9%A1%B9%E7%9B%AE/">项目</a>
    
    <a href="https://luckly.work/tags/%E9%AD%85%E5%8A%9B/">魅力</a>
    
</div>
    </section>

    
<section class="widget">
    <h3 class="widget-title">友情链接</h3>
    <ul class="widget-list">
        
        <li>
            <a target="_blank" href="http://www.topgoer.com/" title="枯藤">枯藤</a>
        </li>
        
        <li>
            <a target="_blank" href="https://gorm.cn/zh_CN/docs/index.html" title="gorm">gorm</a>
        </li>
        
        <li>
            <a target="_blank" href="https://docs.python.org/zh-cn/3/tutorial/index.html" title="python">python</a>
        </li>
        
        <li>
            <a target="_blank" href="https://www.liwenzhou.com/" title="李文周">李文周的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="http://www.xbzweb.com/" title="小包子的博客">小包子的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="https://www.flysnow.org/" title="飞雪无情的博客">飞雪无情的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="https://sliverhorn.com/" title="sliverhorn的博客">sliverhorn的博客</a>
        </li>
        
        <li>
            <a target="_blank" href="http://yuedu.baidu.com/ebook/14a722970740be1e640e9a3e" title="Android Gradle权威指南">Android Gradle权威指南</a>
        </li>
        
        <li>
            <a target="_blank" href="https://gesdh.cn/" title="小格子">格子导航</a>
        </li>
        
        <li>
            <a target="_blank" href="https://itachi.xyz/" title="阿林">itachi&#39;s Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="https://darjun.github.io/" title="大俊">大俊Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="https://geektutu.com/post/quick-golang.html" title="极客兔兔">极客兔兔Blog</a>
        </li>
        
        <li>
            <a target="_blank" href="http://zxfcumtcs.github.io/" title="赵雪峰">雪峰Blog</a>
        </li>
        
    </ul>
</section>


    <section class="widget">
        <h3 class="widget-title">其它</h3>
        <ul class="widget-list">
            <li><a href="https://luckly.work/index.xml">文章 RSS</a></li>
        </ul>
    </section>
</div>
            </div>
        </div>
    </div>
</body>

</html>